#include "GLTwoTriangleWindow.h"

GLTwoTriangleWindow::GLTwoTriangleWindow(QWidget* parent)
	: QOpenGLWidget(parent)
{
	this->resize(QSize(480, 480));
	this->setWindowTitle("使用一个顶点数组绘制两个三角形");
	this->setWindowIcon(QIcon("images/opencv.png"));
}
void GLTwoTriangleWindow::initializeGL() {
	initializeOpenGLFunctions();
	//清屏颜色
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
	qDebug() << "初始化成功";
	
	//// vertex shader
	//unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
	//glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	//glCompileShader(vertexShader);
	//// check for shader compile errors
	//int success;
	//char infoLog[512];
	//glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
	//if (!success)
	//{
	//	glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
	//	qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog;
	//}
	//// fragment shader
	//unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	//glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	//glCompileShader(fragmentShader);
	//// check for shader compile errors
	//glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
	//if (!success)
	//{
	//	glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
	//	qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog;
	//}
	//// link shaders
	//glAttachShader(programId, vertexShader);
	//glAttachShader(programId, fragmentShader);
	//glLinkProgram(programId);
	//// check for linking errors
	//glGetProgramiv(programId, GL_LINK_STATUS, &success);
	//if (!success) {
	//	glGetProgramInfoLog(programId, 512, NULL, infoLog);
	//	qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog;
	//}
	//glDeleteShader(vertexShader);
	//glDeleteShader(fragmentShader);

	//包含：着色器创建、绑定、解绑、链接
	createAndLinkProgram(GL_VERTEX_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.vert"
		, GL_FRAGMENT_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.frag");

	//创建顶点数组对象VAO用来管理VBO
	glGenVertexArrays(1, &VAO);
	//创建顶点缓冲对象
	glGenBuffers(1, &VBO);

	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//将顶点数据放入VBO中
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	//告知显卡应该如何解析顶点
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	//释放VAO、VBO状态
	//glBindBuffer(GL_ARRAY_BUFFER, 0);
	//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	//glBindVertexArray(0);
}
void GLTwoTriangleWindow::createAndLinkProgram(GLenum vertexShaderType, QString vertexResPath,
	GLenum fragmentShaderType, QString fragmentResPath) {
	//编译顶点着色器和片元着色器
	GLuint vertexShader = getShaderId(GL_VERTEX_SHADER, vertexResPath);
	GLuint fragmentShader = getShaderId(GL_FRAGMENT_SHADER, fragmentResPath);
	programId = glCreateProgram();
	glAttachShader(programId, vertexShader);
	glAttachShader(programId, fragmentShader);
	glLinkProgram(programId);
	int success;
	char infoLog[512];
	glGetProgramiv(programId, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(programId, 512, NULL, infoLog);
		qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog;
	}
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);
}
GLuint GLTwoTriangleWindow::getShaderId(GLenum shaderType, QString resPath) {
	//创建顶点着色器
	unsigned int shaderId = glCreateShader(shaderType);
	QFile vertexShaderFile(resPath);
	if (!vertexShaderFile.open(QIODevice::ReadOnly)) {
		qDebug() << "Cannot open vertex shader file for reading";
	}
	QString verQStr = vertexShaderFile.readAll();
	std::string verStdStr = verQStr.toStdString();
	const char* vertexStr = verStdStr.c_str();
	qDebug() << "vertexStr-------------" << vertexStr;
	vertexShaderFile.close();
	glShaderSource(shaderId, 1, &vertexStr, NULL);
	glCompileShader(shaderId);
	int success;
	char infoLog[512];
	glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
		qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog;
	}
	return shaderId;
}
void GLTwoTriangleWindow::resizeGL(int w, int h) {
	glViewport(0, 0, w, h);
}
void GLTwoTriangleWindow::paintGL() {
	glUseProgram(programId);
	glBindVertexArray(VAO);
	glDrawArrays(GL_TRIANGLES, 0,6);
}
GLTwoTriangleWindow::~GLTwoTriangleWindow()
{
	/*glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(programId);*/
}
